package jnpf.engine.custom.type;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import java.util.ArrayList;
import jnpf.engine.assembly.UserTaskExPropertyDTO;
import jnpf.engine.assembly.prop.UserTaskNodeEventDTO;
import jnpf.engine.custom.constants.BasicActivitiConstants;
import jnpf.engine.custom.constants.RootExecutionVariableConstants;
import jnpf.engine.custom.variables.entity.FormDataInfo;
import jnpf.engine.entity.FlowTaskOperatorRecordEntity;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ChildNodeList;
import jnpf.engine.util.*;
import jnpf.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.impl.RepositoryServiceImpl;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

import static jnpf.engine.custom.constants.GlobalProcessVariableConstants.*;
import static jnpf.engine.custom.constants.RootExecutionVariableConstants.*;
import static jnpf.engine.util.BpmnModelUtils.*;

/**
 * @author LoveMyOrange
 * @create 2022-01-18 17:22
 */
@Slf4j
@Component
public class TaskCompletedListener implements FlowableEventListener {
    @Override
    public void onEvent(FlowableEvent activitiEvent) {
        if (!(activitiEvent instanceof FlowableEntityEventImpl)) {
            return;
        }
        FlowableEntityEventImpl activitiEntityEventImpl = (FlowableEntityEventImpl) activitiEvent;
        Object entity = activitiEntityEventImpl.getEntity();

        if (!(entity instanceof TaskEntity)) {
            return;
        }
        FlowMsgUtil flowMsgUtil = SpringContextHolder.getBean(FlowMsgUtil.class);
        TaskEntity taskEntity = (TaskEntity) entity;
        String taskDefinitionKey = taskEntity.getTaskDefinitionKey();
        RepositoryServiceImpl repositoryService = SpringContextHolder.getBean(RepositoryServiceImpl.class);
        Process mainProcess = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId()).getMainProcess();

        FlowTaskUtil flowTaskUtil = SpringContextHolder.getBean(FlowTaskUtil.class);
        String formKey = taskEntity.getFormKey();
        String[] split = formKey.split(BasicActivitiConstants.taskDescriptionSeparator);
        Map<String, Object> result = flowTaskUtil.infoData(split[0], split[1]);
        Map<String, Object> variables = taskEntity.getVariables();
        Integer auditNum = MapUtil.getInt(variables, MULTI_INSTANCE_NUM_AUDIT);
        Integer rejectNum = MapUtil.getInt(variables, MULTI_INSTANCE_NUM_REJECT);
        Integer abstentionNum = MapUtil.getInt(variables, MULTI_INSTANCE_NUM_ABSTENTION);
        List assigneeList = MapUtil.get(variables, taskDefinitionKey + "assigneeList", List.class);
        result.put(MULTI_INSTANCE_NUM_AUDIT,auditNum);
        result.put(MULTI_INSTANCE_NUM_REJECT,rejectNum);
        result.put(MULTI_INSTANCE_NUM_ABSTENTION,abstentionNum);
        result.put(TryEvaluateUtils.NODE_ASSIGNEE,assigneeList);
        FlowContextHolder.addNodeFormData(taskDefinitionKey,result);

        taskEntity.setTransientVariables(result);

        UserTask firstNode = getFirstNode(mainProcess);
        if(!taskEntity.getTaskDefinitionKey().equals(firstNode.getId())){
            if(StringUtils.isBlank(taskEntity.getParentTaskId())){
                List variable = taskEntity.getVariable(COMPLETED_USERS_IDS, List.class);
                if(variable==null){
                    List<String> list=new ArrayList<>();
                    list.add(taskEntity.getAssignee());
                    taskEntity.setVariable(COMPLETED_USERS_IDS,list);
                }
                else{
                    variable.add(taskEntity.getAssignee());
                    ArrayList distinct = CollUtil.distinct(variable);
                    taskEntity.setVariable(COMPLETED_USERS_IDS,distinct);
                }
            }

        }
        log.info("任务完成监听器触发.."+activitiEvent.getClass());
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }
}
